Remove an access right for a user from a module and the corresponding link module

Hi all,

How do I remove a specific access right, say "delete" for a particular user from a module and its corresponding link module? Assuming that user already has say, read, create, delete and modify access.

 

Any help will be very much appreciated. Thanks in advance.


cron7 - Thu Feb 08 06:13:40 EST 2018

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Thu Feb 08 07:59:40 EST 2018

First advise: don't do this. Never work with access rights with personal user accounts, always work with groups, or you will get in permission maintenance hell sooner or later.

 

then: In case you have not done this, I think it is the easiest, if you read the chapter "Access Rights" of the DOORS manual and understand access records, permissions, access rights propagation. 

First, you will have to determine how this user got his right to delete an object. Do that without DxL first, to understand what happens (Properties->Access).

  • Does the user have his own access record that you can manipulate -> fine, delete the D Permission
  • Is this user member of a group and is that the reason why he got the "D" right? -> Perhaps you should remove this user from the group -- but does he have enough access rights now? Perhaps you want to create a group "no delete for project x" and set access rights for this group and add this user to this group?
  • Is there no special permission and "Everoyone else" has "D" rights? Hm, you will first have to explain why everyone in the world has delete rights but not this one user. After the explanation is good enough for you and the database administrators, either you set up a good group structure and remove D right for everyone else, instead give it to a "special user for project x" group and set preferences accordingly. Or you create a special access record for this specific user where he has all access rights he needs besides deleting. This is possible as specific user rights have a higher preference than general access rights.
  • In each case, remember
    • that preferences can be inherited (so it might happen that there is no access record for a module, only for one of its parent folders or projects),
    • that there is access right propagation which you might need, the user might have received his D rights by getting C, propagate MD or C, propagate MDA on a higher level.
    • that EVERY SINGLE object might have its own access records, in case not all access rights are inherited downwards: if you remove D right for the module, the user might still be able to delete an object on level 3 or 4.
    • that implementation of "Set up module for sharing" is done by breaking access inheritance on the defined level -> in this case you will have to find ALL sections and delete the user's D permission on every level.

Now that you know WHAT to do, you want to know HOW to do it. Read DXL manual, chapter 21 (Permissions). 

The general approach would be thus, see the examples in chapter 21:

You will first need to get access to the item (e.g. module) that you want to check, e.g. open the module and store the handle (Module m = read ("/my/module", false, true)). For this item, you need to retrieve all the AccessRec (AccessRec ar ; for ar in all m do {...}) and analyze them according to the above mentioned use cases. E.g. look for an access record for this specific user, (if username(ar) == "myUserID" then ...). Then, in case the user has D rights (if delete(ar)...)  you need a bitwise negation of the permissions, thus removing the D flag. Finally, use the set command (string set (m, p, s), with m being the module, p being the calculated permission and s being the username or group name, and save and close the module.

 

Hope this helps

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Thu Feb 08 08:02:27 EST 2018

Oh, I see that you need to do this not only for Deletion but also for other access types. In that case, remember:

  • read is implied by all other access rights -> remove all permissions if you want to remove "read"
  • modify is implied by delete and control -> remove delete and control
  • create is implied by control, so remove create & control
  • delete is not implied by another, only remove delete    (well, if you remove D (delete), but not A (control), the user will be able to change the permission of the module, so he can give the D right back to himself)
  • control is not implied by another, only remove control

 

Have fun...

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Thu Feb 08 08:11:15 EST 2018

One final remark. You want to remove D for a module AND ITS CORRESPONDING LINK MODULE? You know that the objects in a Link Module are Link sets?
Well, yes, it's a common use case not to allow the deletion of link sets to ordinary users. But in this case, when thinking about a good access rights structure, you should rather think about removing D  for EVERY user besides some special data model administration group. You even might want to completely disable M rights of link modules for ordinary users, in case you have a centralized data model roll out mechanism.

Re: Remove an access right for a user from a module and the corresponding link module
cron7 - Fri Feb 09 05:36:16 EST 2018

Mike.Scharnow - Thu Feb 08 07:59:40 EST 2018

First advise: don't do this. Never work with access rights with personal user accounts, always work with groups, or you will get in permission maintenance hell sooner or later.

 

then: In case you have not done this, I think it is the easiest, if you read the chapter "Access Rights" of the DOORS manual and understand access records, permissions, access rights propagation. 

First, you will have to determine how this user got his right to delete an object. Do that without DxL first, to understand what happens (Properties->Access).

  • Does the user have his own access record that you can manipulate -> fine, delete the D Permission
  • Is this user member of a group and is that the reason why he got the "D" right? -> Perhaps you should remove this user from the group -- but does he have enough access rights now? Perhaps you want to create a group "no delete for project x" and set access rights for this group and add this user to this group?
  • Is there no special permission and "Everoyone else" has "D" rights? Hm, you will first have to explain why everyone in the world has delete rights but not this one user. After the explanation is good enough for you and the database administrators, either you set up a good group structure and remove D right for everyone else, instead give it to a "special user for project x" group and set preferences accordingly. Or you create a special access record for this specific user where he has all access rights he needs besides deleting. This is possible as specific user rights have a higher preference than general access rights.
  • In each case, remember
    • that preferences can be inherited (so it might happen that there is no access record for a module, only for one of its parent folders or projects),
    • that there is access right propagation which you might need, the user might have received his D rights by getting C, propagate MD or C, propagate MDA on a higher level.
    • that EVERY SINGLE object might have its own access records, in case not all access rights are inherited downwards: if you remove D right for the module, the user might still be able to delete an object on level 3 or 4.
    • that implementation of "Set up module for sharing" is done by breaking access inheritance on the defined level -> in this case you will have to find ALL sections and delete the user's D permission on every level.

Now that you know WHAT to do, you want to know HOW to do it. Read DXL manual, chapter 21 (Permissions). 

The general approach would be thus, see the examples in chapter 21:

You will first need to get access to the item (e.g. module) that you want to check, e.g. open the module and store the handle (Module m = read ("/my/module", false, true)). For this item, you need to retrieve all the AccessRec (AccessRec ar ; for ar in all m do {...}) and analyze them according to the above mentioned use cases. E.g. look for an access record for this specific user, (if username(ar) == "myUserID" then ...). Then, in case the user has D rights (if delete(ar)...)  you need a bitwise negation of the permissions, thus removing the D flag. Finally, use the set command (string set (m, p, s), with m being the module, p being the calculated permission and s being the username or group name, and save and close the module.

 

Hope this helps

Hi Mike. Thanks a lot for all the knowledge you shared. It's really helpful. Being new to dxl, I was missing out on quite a few things.

Just one thing, what do you mean by "I need bitwise negation to remove permissions" Could you give an instance?

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Fri Feb 09 07:49:19 EST 2018

cron7 - Fri Feb 09 05:36:16 EST 2018

Hi Mike. Thanks a lot for all the knowledge you shared. It's really helpful. Being new to dxl, I was missing out on quite a few things.

Just one thing, what do you mean by "I need bitwise negation to remove permissions" Could you give an instance?

As you can read in Access controls -> Controlling Access -> Operators, each permission represents one bit, being 1 if set and 0 if not set, and the permission to be set is the sum of all bits to be set, Bits are set using | and removed using &.

When a user needs "modify" permission, he also needs "read" permission -> the combined permission to be set is modify "plus" read. As example, imagine that "read" is bit 0, "modify" is bit 1, "delete" is bit 2, "control" is bit 3.

If a user has all read, modify and delete permissions, all the three lower bits are set to 1, the total permission would be 1 + 2 + 4 + 0 = 0111 (7). If you just want to remove the "delete" permission, you would have to ensure that bit 2 (value 4) is removed, all other permissions have to stay as they were, so, you would have to "subtract" 4 from the current permission, but only if the delete bit is currently set, otherwise you would not have to change anything. In C, to do this, you would bitwise negate (xor) the current permissions with "1111 1011".

So much for theory. In reality, you do not need to make it too complicated by using numbers. As you can see from the example in the manual, "all" permissions include

Permission all = read|create|modify|delete|control

To delete "delete" permission, you just have to set all previous permissions that the user had besides "delete"

AccessRec ar = ... the AccessRec I want to look at, e.g. the one from the user
Permission p // the new permission to be set
if (i want to delete "delete" rights from ar)  p = read(ar) | modify(ar) | create(ar) | control(ar)
// where "read(ar)" means: whether in the existing AccessRec the read bit was turned on.

 

Re: Remove an access right for a user from a module and the corresponding link module
cron7 - Mon Feb 12 06:37:19 EST 2018

Mike.Scharnow - Fri Feb 09 07:49:19 EST 2018

As you can read in Access controls -> Controlling Access -> Operators, each permission represents one bit, being 1 if set and 0 if not set, and the permission to be set is the sum of all bits to be set, Bits are set using | and removed using &.

When a user needs "modify" permission, he also needs "read" permission -> the combined permission to be set is modify "plus" read. As example, imagine that "read" is bit 0, "modify" is bit 1, "delete" is bit 2, "control" is bit 3.

If a user has all read, modify and delete permissions, all the three lower bits are set to 1, the total permission would be 1 + 2 + 4 + 0 = 0111 (7). If you just want to remove the "delete" permission, you would have to ensure that bit 2 (value 4) is removed, all other permissions have to stay as they were, so, you would have to "subtract" 4 from the current permission, but only if the delete bit is currently set, otherwise you would not have to change anything. In C, to do this, you would bitwise negate (xor) the current permissions with "1111 1011".

So much for theory. In reality, you do not need to make it too complicated by using numbers. As you can see from the example in the manual, "all" permissions include

Permission all = read|create|modify|delete|control

To delete "delete" permission, you just have to set all previous permissions that the user had besides "delete"

AccessRec ar = ... the AccessRec I want to look at, e.g. the one from the user
Permission p // the new permission to be set
if (i want to delete "delete" rights from ar)  p = read(ar) | modify(ar) | create(ar) | control(ar)
// where "read(ar)" means: whether in the existing AccessRec the read bit was turned on.

 

Thanks again Mike.

What I am trying is, if "modify" rights are already present for groups at module level, I should also grant them "delete" rights.

I'm trying to apply this for different users/groups for a module, but it doesn't work. However, when I apply those changes to its parent folder, same changes get reflected in the module.
Any idea on as to why this is happening? Does the set(mod,delete,"groupName") have any exceptions with respect to modules?

 

Thanks in advance.

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Mon Feb 12 08:32:11 EST 2018

cron7 - Mon Feb 12 06:37:19 EST 2018

Thanks again Mike.

What I am trying is, if "modify" rights are already present for groups at module level, I should also grant them "delete" rights.

I'm trying to apply this for different users/groups for a module, but it doesn't work. However, when I apply those changes to its parent folder, same changes get reflected in the module.
Any idea on as to why this is happening? Does the set(mod,delete,"groupName") have any exceptions with respect to modules?

 

Thanks in advance.

Hi cron7,

that would be the sentence

In each case, remember

  • that preferences can be inherited (so it might happen that there is no access record for a module, only for one of its parent folders or projects),

It is totally possible to set access rights somewhere at the top and set all "children" (that might be projects, folders, modules, objects) to "inherit from parent". So, it depends on what you want: shall the different rights only be applied for some specific modules? In this case, you have to break the inheritance -> the module has its "own" access rights that you can modify, otherwise just set the rights at the parent level.

To break the inheritance, look at the perms "specific, specificDef, specificVal" in the DXL manual, but remember that this will break the inheritance for all rights, not just for this one group/user or the "delete" right.

 

 

Re: Remove an access right for a user from a module and the corresponding link module
cron7 - Tue Feb 13 05:07:09 EST 2018

Mike.Scharnow - Mon Feb 12 08:32:11 EST 2018

Hi cron7,

that would be the sentence

In each case, remember

  • that preferences can be inherited (so it might happen that there is no access record for a module, only for one of its parent folders or projects),

It is totally possible to set access rights somewhere at the top and set all "children" (that might be projects, folders, modules, objects) to "inherit from parent". So, it depends on what you want: shall the different rights only be applied for some specific modules? In this case, you have to break the inheritance -> the module has its "own" access rights that you can modify, otherwise just set the rights at the parent level.

To break the inheritance, look at the perms "specific, specificDef, specificVal" in the DXL manual, but remember that this will break the inheritance for all rights, not just for this one group/user or the "delete" right.

 

 

Hi Mike, here is what is happening :

 

---> When "inherit from parent" is checked for module, and whether I run the code with or WITHOUT specific(mod), to change the access rights of the module's parent project/folder, the changes get reflected in the project/folder AND MODULE TOO.

 

---> When "inherit from parent" is checked for module, and whether I run the code with or WITHOUT specific(mod), to change the access rights of the MODULE ALONE, the changes DO NOT get reflected in the MODULE. And the "inherit from parent" gets unchecked.

 

Do you know of any fix? Thanks in advance.

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Tue Feb 13 05:48:18 EST 2018

cron7 - Tue Feb 13 05:07:09 EST 2018

Hi Mike, here is what is happening :

 

---> When "inherit from parent" is checked for module, and whether I run the code with or WITHOUT specific(mod), to change the access rights of the module's parent project/folder, the changes get reflected in the project/folder AND MODULE TOO.

 

---> When "inherit from parent" is checked for module, and whether I run the code with or WITHOUT specific(mod), to change the access rights of the MODULE ALONE, the changes DO NOT get reflected in the MODULE. And the "inherit from parent" gets unchecked.

 

Do you know of any fix? Thanks in advance.

1. well, that's the idea behind inheritance.when you change something at the top, the changes shall be reflected at the children (say, in project p1, user u1 and group g1 have RMCD rights, and this shall be so for every folder and module in p1. If you remove D for g1 and u1, this change will be shown in all children). Or what is the question that you have?

 

2. it should work if you firsrt set specific(mod) -> the check box is unchecked the current access rights are copied (as opposed to "linked") from the parent to the module. Then in the next step you can change the rights, e.g. by removing D for g1 and/or u1

Re: Remove an access right for a user from a module and the corresponding link module
cron7 - Thu Feb 15 05:08:19 EST 2018

Mike.Scharnow - Tue Feb 13 05:48:18 EST 2018

1. well, that's the idea behind inheritance.when you change something at the top, the changes shall be reflected at the children (say, in project p1, user u1 and group g1 have RMCD rights, and this shall be so for every folder and module in p1. If you remove D for g1 and u1, this change will be shown in all children). Or what is the question that you have?

 

2. it should work if you firsrt set specific(mod) -> the check box is unchecked the current access rights are copied (as opposed to "linked") from the parent to the module. Then in the next step you can change the rights, e.g. by removing D for g1 and/or u1

Hi Mike, a doubt :

Currently, when I am adding "delete" access to the certain user groups in a module in the following way :


---> Usergroup1 already having "RMC" rights, when I add set(mod, delete, "Usergroup1"), the access rights change to "RMD". It should change to "RMCD", right?
---> Usergroup2 already having "RM" rights, when I add set(mod, delete, "Usergroup2"), the access rights change to "RMD". It should change to "RMD", right?
---> Usergroup3 already having "RMCD" rights, when I add set(mod, delete, "Usergroup3"), the access rights change to "RMD". It should remain  "RMCD", right?

 

i.e, basically this my code :

AccessRec arr

for arr in all mod do
{
    if(modify arr && username(arr)!= "Usergroup")
    {
         print username(arr) "\t"
         set(mod,delete, username(arr))
     }
}

 

Any idea as to why this is happening? Correct me if I am wrong anywhere. Thanks in advance. :)

Re: Remove an access right for a user from a module and the corresponding link module
cron7 - Thu Feb 15 06:24:43 EST 2018

Mike.Scharnow - Fri Feb 09 07:49:19 EST 2018

As you can read in Access controls -> Controlling Access -> Operators, each permission represents one bit, being 1 if set and 0 if not set, and the permission to be set is the sum of all bits to be set, Bits are set using | and removed using &.

When a user needs "modify" permission, he also needs "read" permission -> the combined permission to be set is modify "plus" read. As example, imagine that "read" is bit 0, "modify" is bit 1, "delete" is bit 2, "control" is bit 3.

If a user has all read, modify and delete permissions, all the three lower bits are set to 1, the total permission would be 1 + 2 + 4 + 0 = 0111 (7). If you just want to remove the "delete" permission, you would have to ensure that bit 2 (value 4) is removed, all other permissions have to stay as they were, so, you would have to "subtract" 4 from the current permission, but only if the delete bit is currently set, otherwise you would not have to change anything. In C, to do this, you would bitwise negate (xor) the current permissions with "1111 1011".

So much for theory. In reality, you do not need to make it too complicated by using numbers. As you can see from the example in the manual, "all" permissions include

Permission all = read|create|modify|delete|control

To delete "delete" permission, you just have to set all previous permissions that the user had besides "delete"

AccessRec ar = ... the AccessRec I want to look at, e.g. the one from the user
Permission p // the new permission to be set
if (i want to delete "delete" rights from ar)  p = read(ar) | modify(ar) | create(ar) | control(ar)
// where "read(ar)" means: whether in the existing AccessRec the read bit was turned on.

 

Also Mike, this doesn't work. I get the following error :

-E- DXL: <Line:25> incorrect arguments for (|)
-E- DXL: <Line:25> incorrect arguments for (|)
-E- DXL: <Line:25> incorrect arguments for (|)
-E- DXL: <Line:25> incorrect arguments for (=)
-I- DXL: All done. Errors reported: 4. Warnings reported: 0.

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Thu Feb 15 06:33:06 EST 2018

cron7 - Thu Feb 15 05:08:19 EST 2018

Hi Mike, a doubt :

Currently, when I am adding "delete" access to the certain user groups in a module in the following way :


---> Usergroup1 already having "RMC" rights, when I add set(mod, delete, "Usergroup1"), the access rights change to "RMD". It should change to "RMCD", right?
---> Usergroup2 already having "RM" rights, when I add set(mod, delete, "Usergroup2"), the access rights change to "RMD". It should change to "RMD", right?
---> Usergroup3 already having "RMCD" rights, when I add set(mod, delete, "Usergroup3"), the access rights change to "RMD". It should remain  "RMCD", right?

 

i.e, basically this my code :

AccessRec arr

for arr in all mod do
{
    if(modify arr && username(arr)!= "Usergroup")
    {
         print username(arr) "\t"
         set(mod,delete, username(arr))
     }
}

 

Any idea as to why this is happening? Correct me if I am wrong anywhere. Thanks in advance. :)

set(mod,right,user) will SET the given access right, it will not ADD the right. 

As written above, read is implied by all other access rights and modify is implied by delete. So, when you set "delete", you implicitely set R and M as well, as these are needed for D.

If you need to ADD D right, you need to find out which rights existed before.

--> usergroup having RMC rights: set delete()|modify() : "add" delete "plus" modify

--> usergrup having RM: set delete()

--> usergroup having RMCD: don't change anything

--> also add control() if usergroup have A

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Thu Feb 15 06:33:58 EST 2018

cron7 - Thu Feb 15 06:24:43 EST 2018

Also Mike, this doesn't work. I get the following error :

-E- DXL: <Line:25> incorrect arguments for (|)
-E- DXL: <Line:25> incorrect arguments for (|)
-E- DXL: <Line:25> incorrect arguments for (|)
-E- DXL: <Line:25> incorrect arguments for (=)
-I- DXL: All done. Errors reported: 4. Warnings reported: 0.

when code throws errorsr and you ask for help about it, it is always a good idea to post the code that throws the error :-)

Re: Remove an access right for a user from a module and the corresponding link module
cron7 - Thu Feb 15 06:39:51 EST 2018

Mike.Scharnow - Thu Feb 15 06:33:58 EST 2018

when code throws errorsr and you ask for help about it, it is always a good idea to post the code that throws the error :-)

Sorry for that. Here is the code :
 

void processFormal(string mName)
{
        print("Formal Module: " mName "\n")
        
        
        Module mod = edit(mName, false)
        AccessRec ar
        Permission p
        for ar in all mod do
        {
                if(delete ar)
                {
                        print "Hi"
                        p = read(ar)|modify(ar)|create(ar)|control(ar)
                        set(mod,p,username(ar))
                }
        }
}

 

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Thu Feb 15 07:20:31 EST 2018

cron7 - Thu Feb 15 06:39:51 EST 2018

Sorry for that. Here is the code :
 

void processFormal(string mName)
{
        print("Formal Module: " mName "\n")
        
        
        Module mod = edit(mName, false)
        AccessRec ar
        Permission p
        for ar in all mod do
        {
                if(delete ar)
                {
                        print "Hi"
                        p = read(ar)|modify(ar)|create(ar)|control(ar)
                        set(mod,p,username(ar))
                }
        }
}

 

p=read()|modify()|create)()|control()

or

p=read|modify|create|control

Re: Remove an access right for a user from a module and the corresponding link module
Mike.Scharnow - Thu Feb 15 07:33:15 EST 2018

Mike.Scharnow - Thu Feb 15 07:20:31 EST 2018

p=read()|modify()|create)()|control()

or

p=read|modify|create|control

  • "read()", as in "Permission p = read()" returns a Permission needed to set permissions for users.
  • "read" without the brackets is the same as read(), brackets are optional in DXL if there is only one or zero parameters.
  • "read(AccessRec)" returns a boolean value, it is needed to detect whether the AccessRec includes R.